import { Injectable, NotFoundException } from '@nestjs/common';
import { CreateSceneListDto } from './dto/create-scene-list.dto';
import { UpdateSceneListDto } from './dto/update-scene-list.dto';
import { In, Repository, getManager } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { SceneList } from './entities/scene-list.entity';
import { RawGroupToScenceList } from './dto/create-grouptoscene.dto';
import { GroupToScence } from './entities/grouptoscene.entity';
import { User } from 'src/user/entities/user.entity';
import { usertogroup } from 'src/group/entities/usertogroup.entity';
import { SceneFileRelationalService } from 'src/scene_file_relational/scene_file_relational.service';
import { ScenePathRelational } from 'src/scene_path_relational/entities/scene_path_relational.entity';
import { PathList } from 'src/path-list/entities/path-list.entity';
import { PathListService } from 'src/path-list/path-list.service';
import { PathItemRelational } from 'src/path-item-relational/entities/path-item-relational.entity';
import { CameraRotateService } from 'src/camera-rotate/camera-rotate.service';
import { AudioService } from 'src/audio/audio.service';
import { TextService } from 'src/text/text.service';
import { VideoService } from 'src/video/video.service';
import { PictureService } from 'src/picture/picture.service';
import { CameraalongService } from 'src/cameraalong/cameraalong.service';
import { DynamiclayerService } from 'src/dynamiclayer/dynamiclayer.service';
import { GeojsonService } from 'src/geojson/geojson.service';
import { ImagerasterService } from 'src/imageraster/imageraster.service';
import { MapEaseService } from 'src/map-ease/map-ease.service';
import { MarkerService } from 'src/marker/marker.service';
import { UpdateGroupToScenceListDto } from './dto/update-grouptoscene.dto';
import { CreatePathListDto } from 'src/path-list/dto/create-path-list.dto';
import { CreateScenePathRelationalDto } from 'src/scene_path_relational/dto/create-scene_path_relational.dto';

@Injectable()
export class SceneListService {
  constructor(
    @InjectRepository(SceneList)
    private readonly sceneListRepository: Repository<SceneList>,
    @InjectRepository(GroupToScence)
    private readonly groupToScenceRepository: Repository<GroupToScence>,
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
    @InjectRepository(usertogroup)
    private readonly usertogroupRepository: Repository<usertogroup>,
    private readonly sceneFileRelationalService: SceneFileRelationalService,
    @InjectRepository(ScenePathRelational)
    private readonly scenePathRelationalPaRepository: Repository<ScenePathRelational>,
    private readonly pathListService: PathListService,
    private readonly cameraRotateService: CameraRotateService,
    private readonly audioService: AudioService,
    private readonly textService: TextService,
    private readonly videoService: VideoService,
    private readonly pictureService: PictureService,
    private readonly cameraalongService: CameraalongService,
    private readonly dynamiclayerService: DynamiclayerService,
    private readonly geojsonService: GeojsonService,
    private readonly imagerasterService: ImagerasterService,
    private readonly mapEaseService: MapEaseService,
    private readonly markerService: MarkerService,
    @InjectRepository(PathItemRelational)
    private readonly pathItemRelationalRepository: Repository<PathItemRelational>,
    @InjectRepository(PathList)
    private readonly pathListRepository: Repository<PathList>,
  ) {}
  async create(
    createSceneListDto: CreateSceneListDto,
    path_flag: boolean = true,
  ) {
    const sceneList = this.sceneListRepository.create(createSceneListDto);
    const insertResearch = await this.sceneListRepository.insert(sceneList);
    if (path_flag) {
      // 默认添加一个mapEase轨道
      const createPathListDto = new CreatePathListDto();
      createPathListDto.creator = createSceneListDto.creator;
      createPathListDto.type = 'MapEase';
      createPathListDto.ord = 7;
      createPathListDto.visual = true;
      const path_uuid = (
        await this.pathListRepository.insert(
          this.pathListRepository.create(createPathListDto),
        )
      ).raw[0].id;
      // 建立场景轨道之间关系
      const createScenePathRelationalDto = new CreateScenePathRelationalDto();
      createScenePathRelationalDto.path_id = path_uuid;
      createScenePathRelationalDto.scene_id = insertResearch.raw[0].id;
      await this.scenePathRelationalPaRepository.insert(
        this.scenePathRelationalPaRepository.create(
          createScenePathRelationalDto,
        ),
      );
    }

    return insertResearch.raw[0].id;
  }

  async findAll(): Promise<SceneList[]> {
    return this.sceneListRepository.find();
  }

  async findOne(id: string): Promise<SceneList> {
    return this.sceneListRepository.findOne({ where: { id: id } });
  }

  async checkScenceById(id: string) {
    const res = await this.findOne(id);
    if (res === null) {
      return false;
    } else {
      return true;
    }
  }

  async checkScenceBelongGroup(jsonData: {
    scenceuuid: string;
    groupuuid: string;
  }) {
    const res = await this.groupToScenceRepository.findOne({
      where: {
        scenceuuid: jsonData.scenceuuid,
        groupuuid: jsonData.groupuuid,
      },
    });

    if (res === null) {
      return false;
    } else {
      return true;
    }
  }
  async checkScenceBelongUser(id: string, email: any) {
    const res = await this.sceneListRepository.findOne({
      where: { id: id, creator: email },
    });
    if (res === null) {
      return false;
    } else {
      return true;
    }
  }

  getAllSceneItemByUser(creator: string) {
    // 涉及到 group 概念之后要重新修改
    return this.sceneListRepository.find({
      where: { creator: creator, role: 'person', scene_type: 'user' },
    });
  }

  async update(id: string, updateSceneListDto: UpdateSceneListDto) {
    const result = await this.sceneListRepository.update(
      id,
      updateSceneListDto,
    );

    if (result.affected === 0) {
      throw new NotFoundException(`Picture with ID "${id}" not found.`);
    }
  }

  async remove(id: string) {
    // 查村 item 中的信息
    const res = await this.getPathByPathIdsBySceneId(id);
    res.forEach(async (pathItem) => {
      await this.scenePathRelationalPaRepository.delete({
        path_id: pathItem.id,
        scene_id: id,
      });
      this.pathListService.remove(pathItem.id);
    });
    const resItem = await this.findItemsByScenceIdToPath(id);
    resItem.forEach(async (item: any) => {
      await this.pathItemRelationalRepository.delete({ item_id: item.id });
      switch (item.itemType) {
        case 'Picture':
          await this.pictureService.remove(item.id);
          break;
        case 'Video':
          await this.videoService.remove(item.id);
          break;
        case 'Audio':
          await this.audioService.remove(item.id);
          break;
        case 'Text':
          await this.textService.remove(item.id);
          break;
        case 'CameraRotate':
          await this.cameraRotateService.remove(item.id);
          break;
        case 'CameraAlong':
          await this.cameraalongService.remove(item.id);
          break;
        case 'Dynamiclayer':
          await this.dynamiclayerService.remove(item.id);
          break;
        case 'GeoJson':
          await this.geojsonService.remove(item.id);
          break;
        case 'ImageRaster':
          await this.imagerasterService.remove(item.id);
          break;
        case 'MapEase':
          await this.mapEaseService.remove(item.id);
          break;
        case 'Marker':
          await this.markerService.remove(item.id);
          break;
      }
    });
    await this.sceneFileRelationalService.removeBySceneId(id);
    //删除场景
    try {
      return this.sceneListRepository.delete({ id: id });
    } catch (error) {
      return `删除失败`;
    }
  }

  async getPathByPathIdsBySceneId(scene_id: string) {
    const pathList = await this.scenePathRelationalPaRepository.find({
      where: { scene_id: scene_id },
      select: ['path_id'],
    });
    if (pathList.length === 0) return [];
    const pathIdList = pathList.map((item) => item.path_id);
    const pathListResult =
      await this.pathListService.getPathByPathIds(pathIdList);
    return pathListResult;
  }

  async isScenceItemExist(scenceId: string) {
    try {
      await this.sceneListRepository.findOne({
        where: { id: scenceId },
      });
      return true;
    } catch {
      return false;
    }
  }

  // 创建 小组和场景之间的关系
  async deleteScenceItemFromGroup(scenceToGroupId: string) {
    try {
      //删除原本信息
      const scenceTogroupInfo = await this.groupToScenceRepository.findOne({
        where: { id: scenceToGroupId },
      });
      await this.remove(scenceTogroupInfo.scenceuuid);
      return this.groupToScenceRepository.delete({
        id: scenceToGroupId,
      });
    } catch (err) {
      console.error('删除记录失败', err);
      throw '删除记录失败';
    }
  }
  async deleteScenceItemFromGroupByScenceuuid(scenceuuid: string) {
    try {
      await this.remove(scenceuuid);
      return this.groupToScenceRepository.delete({
        id: scenceuuid,
      });
    } catch (err) {
      console.error('删除记录失败', err);
      throw '删除记录失败';
    }
  }
  async getScenceItemByGroupuuid(groupuuid: string) {
    const scenceItemList = await this.groupToScenceRepository.find({
      where: { groupuuid: groupuuid },
    });

    const scenceItemOfGroupList = await Promise.all(
      scenceItemList.map(async (item) => {
        const scenceInfo = await this.sceneListRepository.find({
          where: { id: item.scenceuuid },
        });

        if (scenceInfo.length !== 0) {
          const userItem = await this.userRepository.findOne({
            where: { email: item.belong },
          });

          const usertogroupItem = await this.usertogroupRepository.findOne({
            where: { useruuid: userItem.id, groupuuid: groupuuid },
          });

          (scenceInfo[0] as any).creator_nickname =
            usertogroupItem.groupnickname;
          (scenceInfo[0] as any).scenceToGroupId = item.id;
        }

        return scenceInfo[0];
      }),
    );

    return scenceItemOfGroupList;
  }

  async findItemsByScenceIdToPath(scenceId: string) {
    const pathList = await this.findBySceneId(scenceId);
    const promises = pathList.map(async (pathItem) => {
      return await this.getByPathId(pathItem.path_id);
    });

    const tempArray = await Promise.all(promises);
    const result = await Promise.all(
      tempArray.map(async (subArray) => {
        return await Promise.all(
          subArray.map(async (item) => {
            let updatedItem;
            switch (item.type) {
              case 'Picture':
                updatedItem = await this.pictureService.findOne(item.item_id);
                break;
              case 'Video':
                updatedItem = await this.videoService.findOne(item.item_id);
                break;
              case 'Audio':
                updatedItem = await this.audioService.findOne(item.item_id);
                break;
              case 'Text':
                updatedItem = await this.textService.findOne(item.item_id);
                break;
              case 'CameraRotate':
                updatedItem = await this.cameraRotateService.findOne(
                  item.item_id,
                );
                break;
              case 'CameraAlong':
                updatedItem = await this.cameraalongService.findOne(
                  item.item_id,
                );
                break;
              case 'DynamicLayer':
                updatedItem = await this.dynamiclayerService.findOne(
                  item.item_id,
                );
                break;
              case 'GeoJson':
                updatedItem = await this.geojsonService.findOne(item.item_id);
                break;
              case 'ImageRaster':
                updatedItem = await this.imagerasterService.findOne(
                  item.item_id,
                );
                break;
              case 'MapEase':
                updatedItem = await this.mapEaseService.findOne(item.item_id);
                break;
              case 'Marker':
                updatedItem = await this.markerService.findOne(item.item_id);
                break;
            }
            updatedItem.itemType = item.type;
            return updatedItem;
          }),
        );
      }),
    );
    return result;
  }
  async findBySceneId(scene_id: string): Promise<ScenePathRelational[]> {
    return this.scenePathRelationalPaRepository.find({
      where: { scene_id: scene_id },
      select: ['path_id'],
    });
  }

  async getByPathId(path_id: string): Promise<PathItemRelational[]> {
    return this.pathItemRelationalRepository.find({
      where: { path_id: path_id },
      select: ['item_id', 'type'],
    });
  }

  async createSceneItemToGroup(
    createSceneListDto: CreateSceneListDto,
    groupuuid: string,
  ) {
    // 插入scence列表
    const scenceuuid = await this.create(createSceneListDto);
    const rawGroupToScenceList = new RawGroupToScenceList();
    rawGroupToScenceList.belong = createSceneListDto.creator;
    rawGroupToScenceList.scenceuuid = scenceuuid;
    rawGroupToScenceList.groupuuid = groupuuid;
    const groupToScence =
      this.groupToScenceRepository.create(rawGroupToScenceList);
    this.groupToScenceRepository.insert(groupToScence);
    return scenceuuid;
  }

  getGroupToScenceItem(scenceId: string) {
    return this.groupToScenceRepository.findOne({
      where: { scenceuuid: scenceId },
    });
  }

  async unlockAllScences(email: any) {
    const lockedItems = await this.groupToScenceRepository.find({
      where: { locked_by: email },
    });
    if (lockedItems.length === 0) {
      return;
    }
    const updatePromises = lockedItems.map((item) => {
      return this.updateSceneItemToGroup(item.scenceuuid, {
        locked: false,
        locked_by: '',
        lock_timestamp: new Date(),
      });
    });

    await Promise.all(updatePromises);
  }

  async updateSceneItemToGroup(
    scenceId: string,
    updateGroupToScenceListDto: UpdateGroupToScenceListDto,
  ) {
    const oldItem = await this.groupToScenceRepository.findOne({
      where: { scenceuuid: scenceId },
    });
    if (!oldItem) {
      return '该记录不存在';
    }
    try {
      const updateItem = this.groupToScenceRepository.merge(
        oldItem,
        updateGroupToScenceListDto,
      );
      await this.groupToScenceRepository.save(updateItem);
      return '修改记录成功!';
    } catch (err) {
      throw '更新记录失败';
    }
  }

  getAllPublicSceneItem() {
    return this.sceneListRepository.find({
      where: { scene_type: 'public' },
    });
  }
}
